/*async的流程控制*/
const async = require('async');
const fs = require('fs');
const util = require('util');
 
//异步流程控制测试类
function AsyncControlFlowTest() {
 
}
 
AsyncControlFlowTest.prototype = {
    //根据列出的函数来自动计算依赖关系，并根据依赖关系来执行异步操作
    auto: function () {
        //async.auto({
        //    // this function will just be passed a callback
        //    readData: async.apply(fs.readFile, 'data.txt', 'utf-8'),
        //    showData: ['readData', function(results, cb) {
        //        // results.readData is the file's contents
        //        // ...
        //    }]
        //}, callback);
        async.auto({
            get_data: function (callback) {
                //这种会阻塞整个程序，这样不行
                //for(var i=0; i<10000000000; ++i);
 
                console.log('in get_data');
                // async code to get some data
                callback(null, 'data', 'converted to array');
            },
            make_folder: function (callback) {
                console.log('in make_folder');
                // async code to create a directory to store a file in
                // this is run at the same time as getting the data
                callback(null, 'folder');
            },
            write_file: ['get_data', 'make_folder', function (results, callback) {
                //console.log('results:' + util.inspect(results,true));
                console.log('in write_file', JSON.stringify(results));
                // once there is some data and the directory exists,
                // write the data to a file in the directory
                callback(null, 'filename');
            }],
            email_link: ['write_file', function (results, callback) {
                console.log('in email_link', JSON.stringify(results));
                // once the file is written let's email a link to it...
                // results.write_file contains the filename returned by write_file.
                callback(null, {'file': results.write_file, 'email': 'user@example.com'});
            }]
        }, function (err, results) {
            console.log('err = ', err);
            console.log('results = ', results);
        });
    },
 
    //根据依赖项来计算依赖关系，依赖关系以回调函数参数的形式来进行表示
    autoInject: function () {
        //  The example from `auto` can be rewritten as follows:
        //注入模式直接将依赖关系的函数结果作为了输入项
        async.autoInject({
            get_data: function (callback) {
                // async code to get some data
                callback(null, 'data', 'converted to array');
            },
            make_folder: function (callback) {
                // async code to create a directory to store a file in
                // this is run at the same time as getting the data
                callback(null, 'folder');
            },
            //这种注入方式必须要将参数的名称写正确了，参数的名称需要和函数的名称保持一致，
            //这样通过arguments就可以解析出函数的名称，就可以自动的计算出依赖关系了
            write_file: function (get_data, make_folder, callback) {
                // once there is some data and the directory exists,
                // write the data to a file in the directory
                console.log('arguments=' + console.log(util.inspect(arguments.callee.arguments, true)));
                console.log(util.inspect(get_data, true));
                console.log(util.inspect(make_folder, true));
                callback(null, 'filename');
            },
            email_link: function (write_file, callback) {
                // once the file is written let's email a link to it...
                // write_file contains the filename returned by write_file.
                callback(null, {'file': write_file, 'email': 'user@example.com'});
            }
        }, function (err, results) {
            console.log('err = ', err);
            console.log('email_link = ', results.email_link);
        });
    },
 
    //以参数的形式来计算依赖关系的另外一种表现形式
    autoInject2: function () {
       //callback回调函数callback(err, result)，多个result会以数组的形式来提供
        async.autoInject({
            //...
            get_data: function(callback){
               callback(null, 'data', 'convert to array');
            },
            make_folder: function(callback){
               callback(null, 'make_folder');
            },
            //另外一种书写格式，这样写，回调函数的参数就不再是依赖项了，数组前面的最几个数据
            //描述的是依赖的函数，最后一个回调函数会将前几个依赖项的结果作为输入
            //怎么感觉很有管道的味道哦!!!!
            write_file: ['get_data', 'make_folder', function (get_data_arg, make_folder_arg, callback) {
                console.log('get_data:' + util.inspect(get_data_arg, true));
                console.log('make_folder' + util.inspect(make_folder_arg, true));
 
                callback(null, 'filename');
            }],
            email_link: ['write_file', function (write_file, callback) {
                callback(null, {'file': write_file, 'email': 'user@example.com'});
            }]
            //...
        }, function (err, results) {
            console.log('err = ', err);
            console.log('email_link = ', results.email_link);
        });
    },
 
    //货物处理，这个方法和queue的区别在于，cargo只有一个工作函数，该工作函数可以一次传入多个工作对象
    //而queue是会启动多个工作函数，多个工作函数同时异步工作
    //cargo(function(task, callback), taskNum)
    //taskNum是异步函数一次能处理的数据量
    //task是一个数组
    cargo: function(){
        cargoObj = async.cargo(function(task, callback){
            for(var i=0; i<task.length; ++i){
                console.log('当前的任务:' + task[i].name);
            }
 
            for(var i=0; i<1000000000;++i);
            callback();
        }, 3);
 
        for(var i=0; i<39; ++i){
            cargoObj.push({name:'target'+i});
        }
    },
}
 
var aft = new AsyncControlFlowTest();
var filter_member = ['auto']
for (var m in  aft) {
    if (typeof(aft[m]) == 'function' && filter_member.indexOf(m) == -1) {
        console.log('开始测试:' + m);
        aft[m]();
    }
}